package msu.ml.data;

import msu.ml.data.level2.*;
import java.sql.*;

public class FilteredPulseVolumeSQLAdapter implements IPulseVolumeSQLAdapter
{
    private int limit;
    private int features;
    
    public static final int NONE = 0;
    public static final int AZIMUTH = 1;
    public static final int RANGE = 2;
    public static final int REFLECTIVITY = 3; 
    public static final int VELOCITY = 4; 
    public static final int SPECTRUM_WIDTH = 5; 
    public static final int RVARIANCE = 6; 
    public static final int VVARIANCE = 7; 
    public static final int SVARIANCE = 8; 
    public static final int RKURTOSIS = 9; 
    public static final int VKURTOSIS = 10; 
    public static final int SKURTOSIS = 11; 
    public static final int RSKEWNESS = 12; 
    public static final int VSKEWNESS = 13; 
    public static final int SSKEWNESS = 14; 
    public static final int CLASS = 15; 
    public static final int PULSE_ID = 16;
    public static final int ALL = 0xFF;

    public FilteredPulseVolumeSQLAdapter(int limit)
    {
        this.limit = limit;
        this.features = 0;
    }

    public void includeFeature(int feature)
    {
        if(feature == NONE)
            features = 0;
        else if(feature == ALL)
            features = ALL;
        else
            features = features | (1 << (feature - 1));
    }

    public void excludeFeature(int feature)
    {
        if(feature == NONE)
            features = ALL;
        else if(feature == ALL)
            features = NONE;
        else
            features = features & ~(1 << (feature - 1));
    }

    public int getLimit() { return this.limit; }

    public void setLimit(int limit) {this.limit = limit;}

    private int windowSize = 25;
    public int getWindowSize() { return this.windowSize; }
    public void setWindowSize(int size)
    {
        this.windowSize = size;
    }

    public String createQuery(String volumeName)
    {
        String query = "SELECT ";
        if(hasFeature(PULSE_ID))
            query += "pulse_volumes.pulse_id, "; 
        if(hasFeature(AZIMUTH))
            query += "pulse_volumes.azimuth, "; 
        if(hasFeature(RANGE))
            query += "pulse_volumes.range, ";
        if(hasFeature(REFLECTIVITY))
            query += "pulse_volumes.reflectivity, "; 
        if(hasFeature(VELOCITY))
            query += "pulse_volumes.radial_velocity, "; 
        if(hasFeature(SPECTRUM_WIDTH))
            query += "pulse_volumes.spectrum_width, "; 
        if(hasFeature(RVARIANCE))
            query += "pulse_volumes.ref_variance, ";
        if(hasFeature(RKURTOSIS))
            query += "pulse_volumes.ref_kurtosis, ";
        if(hasFeature(RSKEWNESS))
            query += "pulse_volumes.ref_skewness, ";
        if(hasFeature(VVARIANCE))
            query += "pulse_volumes.vel_variance, ";
        if(hasFeature(VKURTOSIS))
            query += "pulse_volumes.vel_kurtosis, ";
        if(hasFeature(VSKEWNESS))
            query += "pulse_volumes.vel_skewness, ";
        if(hasFeature(SVARIANCE))
            query += "pulse_volumes.spec_variance, ";
        if(hasFeature(SKURTOSIS))
            query += "pulse_volumes.spec_kurtosis, ";
        if(hasFeature(SSKEWNESS))
            query += "pulse_volumes.spec_skewness, ";
        if(hasFeature(CLASS))
            query += "sweeps.class ";
        else if(query.lastIndexOf(',') > 0)
            query = query.substring(0, query.lastIndexOf(','));

        query += " FROM volumes, sweeps, pulse_volumes " + 
        "WHERE pulse_volumes.sweep_id = sweeps.sweep_id AND " +
        "sweeps.volume_id = volumes.volume_id AND " + 
        "volumes.ncdc_filename = '" + volumeName + "' ";

        if(limit > 0)
            query += ("ORDER BY RAND() LIMIT " + this.limit);

        query += ";";

        return query;
    }

    public IPulseVolume getPulseVolume(ResultSet result)
    {
        try
        {
            DynamicPulseVolume pv = new DynamicPulseVolume();

            int i = 1;

            if(hasFeature(PULSE_ID))
                pv.addFeature("pulse_id", result.getDouble(i++));
            if(hasFeature(AZIMUTH))
                pv.addFeature("azimuth", result.getDouble(i++));
            if(hasFeature(RANGE))
                pv.addFeature("range", result.getDouble(i++));
            if(hasFeature(REFLECTIVITY))
                pv.addFeature("reflectivity", result.getDouble(i++));
            if(hasFeature(VELOCITY))
                pv.addFeature("velocity", result.getDouble(i++));
            if(hasFeature(SPECTRUM_WIDTH))
                pv.addFeature("spectrumwidth", result.getDouble(i++));
            if(hasFeature(RVARIANCE))
                pv.addFeature("vref", result.getDouble(i++));
            if(hasFeature(RKURTOSIS))
                pv.addFeature("kref", result.getDouble(i++));
            if(hasFeature(RSKEWNESS))
                pv.addFeature("sref", result.getDouble(i++));
            if(hasFeature(VVARIANCE))
                pv.addFeature("vvel", result.getDouble(i++));
            if(hasFeature(VKURTOSIS))
                pv.addFeature("kvel", result.getDouble(i++));
            if(hasFeature(VSKEWNESS))
                pv.addFeature("svel", result.getDouble(i++));
            if(hasFeature(SVARIANCE))
                pv.addFeature("vspec", result.getDouble(i++));
            if(hasFeature(SKURTOSIS))
                pv.addFeature("kspec", result.getDouble(i++));
            if(hasFeature(SSKEWNESS))
                pv.addFeature("sspec", result.getDouble(i++));
            if(hasFeature(CLASS))
                pv.addFeature("class", result.getDouble(i++));

            return pv;
        }
        catch(Exception e) { }

        return null;
    }

    public boolean hasFeature(int feature)
    {
        return (features & (1 << (feature - 1))) == (1 << (feature - 1));
    }
}
